package com.keqiang.chart.impl.axis

import android.view.GestureDetector
import android.view.MotionEvent
import com.keqiang.chart.base.IDataChangeObserver
import com.keqiang.chart.base.ITouchHandler
import com.keqiang.chart.utils.ClickListener
import kotlin.math.abs

/**
 * 处理触摸事件
 *
 * @author Created by wanggaowan on 2022/7/29 13:11
 */
abstract class BaseTouchHandler<C : BaseAxisChart<*>, D>(val chart: C) : ITouchHandler {

    /**
     * 用户触摸点需要高亮内容的数据，主动设置相当于模拟用户点击
     */
    open var touchData: D? = null

    /**
     * 是否可点击
     */
    open var clickEnable: Boolean = true

    /**
     * 是否可滑动选中
     */
    open var moveChosenEnable: Boolean = true

    /**
     * 点击监听
     */
    open var clickListener: ClickListener<D>? = null

    protected open var captureTouchEvent = false

    init {
        chart.addDataChangeObserver(object : IDataChangeObserver {
            override fun onChange() {
                touchData = null
            }
        })
    }

    /**
     * 处理触摸事件
     */
    override fun onTouch(event: MotionEvent): Boolean {
        if (!clickEnable && !moveChosenEnable) {
            return false
        }

        val use = detector.onTouchEvent(event)
        if (event.action == MotionEvent.ACTION_UP
            || event.action == MotionEvent.ACTION_CANCEL) {
            chart.view.parent.requestDisallowInterceptTouchEvent(false)
            return false
        }
        return use
    }

    private val detector =
        GestureDetector(chart.view.context, object : GestureDetector.SimpleOnGestureListener() {
            override fun onDown(e: MotionEvent): Boolean {
                return this@BaseTouchHandler.onDown(e)
            }

            override fun onSingleTapUp(event: MotionEvent): Boolean {
                return this@BaseTouchHandler.onSingleTapUp(event)
            }

            override fun onScroll(e1: MotionEvent?, e2: MotionEvent, distanceX: Float, distanceY: Float): Boolean {
                return this@BaseTouchHandler.onScroll(e1, e2, distanceX, distanceY)
            }
        })

    protected open fun onDown(e: MotionEvent): Boolean {
        captureTouchEvent = false
        chart.view.parent.requestDisallowInterceptTouchEvent(true)
        return true
    }

    protected open fun onSingleTapUp(event: MotionEvent): Boolean {
        if (!clickEnable) {
            return false
        }

        val find = findTouchInRange(event, false)
        clickListener?.invoke(touchData)
        return find
    }

    protected open fun onScroll(e1: MotionEvent?, e2: MotionEvent, distanceX: Float, distanceY: Float): Boolean {
        if (!moveChosenEnable) {
            return false
        }

        if (abs(distanceY) > abs(distanceX)) {
            if (!captureTouchEvent) {
                chart.view.parent.requestDisallowInterceptTouchEvent(false)
            }
            return false
        }

        captureTouchEvent = true
        return findTouchInRange(e2, true)
    }

    protected open fun findTouchInRange(event: MotionEvent, isMove: Boolean): Boolean {
        val data = getTouchData(event.x, event.y, isMove)
        if (data == null) {
            if (!isMove && touchData != null) {
                touchData = null
                chart.view.invalidate()
                return true
            }
            return false
        }

        touchData = data
        chart.view.invalidate()
        return true
    }

    /**
     * 返回触摸点坐标[x],[y]对应位置的高亮数据,如果未找到返回null，这样不会取消上次选中
     */
    abstract fun getTouchData(x: Float, y: Float, isMove: Boolean): D?
}
